﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Xml.Linq;

namespace NB_Controller_Test
{
    public class NB_Protocol
    {
        /* Line 2 means Bytes 
         * Data Len --  PayLoad部分字节数; 
         * CRC      --  PayLoad部分CRC
         *  | Head Flag | Protocol ID | Protocol Version | Data Len | Crc   | PayLoad | Tail Flag |
         *  | 4	        |  1		  |	1	             |  2 		|  2    |    x    |  2        |
         *  |0xbebebebe |  		      |		             |          |       |         |  0xeded   |
        */

        public const UInt32 NB_PROT_HEAD_FLAG = 0xBEBEBEBE;
        public const UInt16 NB_PROT_TAIL_FLAG = 0xEDED;

        public Byte byProlID = 0x01;
        public Byte byProlVer = 0x00;

        public UInt16 unDataLen = 0;
        public UInt16 unCRC = 0;

        public NB_Prol_Payload nbProlPayload = new NB_Prol_Payload();

        public Byte[] GetProlMsgData()
        {
            Byte[] byPayloadData = nbProlPayload.GetProlPayload();
            if (byPayloadData == null)
                return null;

            //DataLen & CRC
            unDataLen = (UInt16)byPayloadData.Length;
            unCRC = GlobalFun.OppCalcCRC(byPayloadData, unDataLen);

            UInt16 uiMsgSize = (UInt16)(Marshal.SizeOf(NB_PROT_HEAD_FLAG) + Marshal.SizeOf(NB_PROT_TAIL_FLAG) + Marshal.SizeOf(byProlID) + Marshal.SizeOf(byProlVer) + Marshal.SizeOf(unCRC) + Marshal.SizeOf(unDataLen) + unDataLen);

            //分包大于0x05c0=1472包时将发送失败，这里后续需要处理...

            int nIndex = 0;
            Byte[] byMsg = new Byte[uiMsgSize];

            GlobalFun.BasicTypeToByteArrayEndian(NB_PROT_HEAD_FLAG, byMsg, nIndex, out nIndex);

            GlobalFun.BasicTypeToByteArrayEndian(byProlID, byMsg, nIndex, out nIndex);
            GlobalFun.BasicTypeToByteArrayEndian(byProlVer, byMsg, nIndex, out nIndex);

            GlobalFun.BasicTypeToByteArrayEndian(unDataLen, byMsg, nIndex, out nIndex);
            GlobalFun.BasicTypeToByteArrayEndian(unCRC, byMsg, nIndex, out nIndex);

            Array.Copy(byPayloadData, 0, byMsg, nIndex, byPayloadData.Length);
            nIndex += byPayloadData.Length;

            GlobalFun.BasicTypeToByteArrayEndian(NB_PROT_TAIL_FLAG, byMsg, nIndex, out nIndex);

            return byMsg;
        }

        public class NB_Prol_Payload
        {
            /// <summary>
            /// 该消息序列号,响应消息时回填请求消息的该值.设备端接收到同源连续相同的序列号消息只处理一个.
            /// </summary>
            public UInt32 ulSeqNum = 0x12345678;
            /// <summary>
            /// 0 无需响应消息;1 需相应消息
            /// </summary>
            public Byte byIsRsp = 0x01;

            /// <summary>
            /// 0x01		对属性操作 操作包括：读,写,上报(设备主动).
            /// 0x02		指命令操作,每条命令都特定的含义
            /// </summary>
            public Byte byContentType = 0x01;

            /// <summary>
            /// 采用JSON格式内容数据,内容类型不同该字段数据格式不同
            /// </summary>
            public string strContentData = string.Empty;

            public Byte[] GetProlPayload()
            {
                try
                {
                    JObject jObj = JObject.Parse(strContentData);
                    //除去多余无效\r\n以及空格
                    //strContentData = jObj.ToString();
                    strContentData = jObj.ToString().Replace("\r\n ", "");
                    strContentData = strContentData.Replace("  ", "");
                }
                catch (Newtonsoft.Json.JsonReaderException jsonEx)
                {
                    string strError = jsonEx.Message;
                    //提取出有效信息，格式化为中文描述
                    string strTrueError = strError.Substring(strError.IndexOf("Path "));
                    string[] strLst = strTrueError.Split(',');

                    string strKeyName = strLst[0].Trim().Substring(strLst[0].Trim().IndexOf(" ") + 1);
                    string strRowPos = strLst[1].Trim().Substring(strLst[1].Trim().IndexOf(" ") + 1);
                    //ColmPos delete .
                    string strColmPos = strLst[2].Trim().Substring(strLst[2].Trim().IndexOf(" ") + 1);
                    strColmPos = strColmPos.TrimEnd('.');

                    strTrueError = "输入的内容不符合Json语法，请确认: " + "\r\n错误关键字：" + strKeyName + "\r\n错误行号：" + strRowPos + "\r\n错误列号：" + strColmPos;

                    System.Windows.MessageBox.Show(strTrueError, "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                    return null;
                }

                UInt16 uiPayloadSize = (UInt16)(Marshal.SizeOf(ulSeqNum) + Marshal.SizeOf(byIsRsp) + Marshal.SizeOf(byContentType) + strContentData.Length);

                int nIndex = 0;
                Byte[] byPayload = new Byte[uiPayloadSize];

                GlobalFun.BasicTypeToByteArrayEndian(ulSeqNum, byPayload, nIndex, out nIndex);
                GlobalFun.BasicTypeToByteArrayEndian(byIsRsp, byPayload, nIndex, out nIndex);
                GlobalFun.BasicTypeToByteArrayEndian(byContentType, byPayload, nIndex, out nIndex);



                Byte[] byContentData = GlobalFun.StringToByteArray(strContentData, Encoding.ASCII);
                //string strrrr = GlobalFun.ByteArrayToString(byContentData, Encoding.ASCII);

                Array.Copy(byContentData, 0, byPayload, nIndex, byContentData.Length);
                nIndex += byContentData.Length;

                return byPayload;
            }
        }

        public static NB_Protocol CreateNew(string strHeadData, string strHeadProlData, string strJsonData, string strEndData)
        {
            /*
             * 
            BE BE BE BE 
            01 01 00 3E 4E B3 00 00 12 34 01 01  
            {
              "reqId": 40,
              "err": 0,
              "prop": {
                "nbBase": {
                  "imei": "867726030008389",
                  "imsi": "460111172007972",
                  "iccid": "8986031745204906541",
                  "nbip": "10.50.188.73"
                }
              }
            }
            ED ED 
             * */

            NB_Protocol nb_Prol = new NB_Protocol();

            try
            {
                nb_Prol.byProlID = GlobalFun.HexStringToByte(strHeadProlData.Substring(0, 2));
                nb_Prol.byProlVer = GlobalFun.HexStringToByte(strHeadProlData.Substring(3, 2));

                nb_Prol.unDataLen = GlobalFun.HexStringToUInt16(strHeadProlData.Substring(6, 5));
                nb_Prol.unCRC = GlobalFun.HexStringToUInt16(strHeadProlData.Substring(12, 5));

                nb_Prol.nbProlPayload.ulSeqNum = GlobalFun.HexStringToUInt32(strHeadProlData.Substring(18, 11));
                nb_Prol.nbProlPayload.byIsRsp = GlobalFun.HexStringToByte(strHeadProlData.Substring(30, 2));
                nb_Prol.nbProlPayload.byContentType = GlobalFun.HexStringToByte(strHeadProlData.Substring(33, 2));
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("strHeadProlData ：" + strHeadProlData + " 存在错误，无法创建NB_Protocol");
            }


            nb_Prol.nbProlPayload.strContentData = strJsonData;
            return nb_Prol;
        }
    }    

    public class NB_ContentTypeManager
    {
        public List<ContentType> contentTypeList = new List<ContentType>();
        public NB_ContentTypeManager()
        {

        }

        private void Init()
        {
            contentTypeList.Clear();
        }

        public void LoadXmlConfig(string strPath)
        {
            Init();

            if (File.Exists(strPath))
            {
                XDocument doc = XDocument.Load(strPath);
                if (doc != null)
                {
                    IEnumerable<XElement> DevTypeList = doc.Root.Elements("ContentType");
                    foreach (var item in DevTypeList)
                    {
                        ContentType freeRat = new ContentType();
                        freeRat.StrTypeName = item.Attribute("TypeName").Value;
                        freeRat.StrTypeJsonBody = item.Element("TypeJsonBody").Value;
                        freeRat.StrTypeJsonBody1 = freeRat.StrTypeJsonBody;

                        contentTypeList.Add(freeRat);
                    }
                }
            }
        }

        public bool UpdateByName(string strTypeName, ContentType contType)
        {
            foreach (ContentType type in contentTypeList)
            {
                if (type.StrTypeName == strTypeName)
                {
                    type.Clone(contType);
                    break;
                }
            }

            return true;
        }

        public ContentType FindJsonBodyByName(string strTypeName)
        {
            foreach (ContentType type in contentTypeList)
            {
                if (type.StrTypeName == strTypeName)
                {
                    return type;
                }
            }

            return null;
        }
    }

    public class ContentType
    {
        private string strTypeName;
        public string StrTypeName
        {
            get
            {
                return strTypeName;
            }
            set
            {
                strTypeName = value;
            }
        }

        /// <summary>
        /// JsonBody 内容，最初由文件读取，后续若发送编辑框输入了内容，则在切换时使用输入的内容
        /// </summary>
        private string strTypeJsonBody;
        public string StrTypeJsonBody
        {
            get
            {
                return strTypeJsonBody;
            }
            set
            {
                strTypeJsonBody = value;
            }
        }

        /// <summary>
        /// JsonBody1 内容，最初由文件读取，后续若发送编辑框输入了内容，则在切换时使用输入的内容
        /// </summary>
        private string strTypeJsonBody1;
        public string StrTypeJsonBody1
        {
            get
            {
                return strTypeJsonBody1;
            }
            set
            {
                strTypeJsonBody1 = value;
            }
        }

        private string strProlID;
        public string StrProlID
        {
            get
            {
                return strProlID;
            }
            set
            {
                strProlID = value;
            }
        }

        private string strProlVer;
        public string StrProlVer
        {
            get
            {
                return strProlVer;
            }
            set
            {
                strProlVer = value;
            }
        }

        private string strIsRsp;
        public string StrIsRsp
        {
            get
            {
                return strIsRsp;
            }
            set
            {
                strIsRsp = value;
            }
        }

        public ContentType()
        {
            strProlID = "0x01";
            strProlVer = "0x01";
            strIsRsp = "0x01";
        }

        public void Clone(ContentType contType)
        {
            StrTypeJsonBody = contType.StrTypeJsonBody;
            StrTypeJsonBody1 = contType.StrTypeJsonBody1;
            StrProlID = contType.StrProlID;
            StrProlVer = contType.StrProlVer;
            StrIsRsp = contType.StrIsRsp;
        }
    }
}
